﻿
using System;

namespace Game.Common.Resources
{
    /// <summary>
    /// Resources are basically the currency of ASC. You use resources to
    ///    buy units, to do research, to propulse your units and lots of other things.
    ///
    ///    ASC has 3 different kinds of Resources:
    ///     - Energy is a volatile resources that is produced by power plants
    ///       and which can not be stored
    ///     - Material is extracted from the ground by mining stations and mostly 
    ///       used for all kinds of construction purposes
    ///     - Fuel is also typically extracted from the ground, for example by oil
    ///       platforms, and used to power units 	 
    ///
    /// This class carries an amount for each type of resource. So a single
    /// instance of this class represents a complete cost or value.
    /// </summary>
    public class GameResources
    {
        public event EventHandler Changed;

        readonly GameResource _Energy = new GameResource(GameResourceType.Energy);
        readonly GameResource _Material = new GameResource(GameResourceType.Material);
        readonly GameResource _Fuel = new GameResource(GameResourceType.Fuel);
        
        public GameResources()
        {
            Watch();
        }
     
        public GameResources(ReadonlyGameResources source)
        {
            _Energy.Set(source.Energy.Value);
            _Fuel.Set(source.Fuel.Value);
            _Material.Set(source.Material.Value);
            Watch();
        }
        
        public GameResources(int energy, int fuel, int material)
        {
            _Energy.Set(energy);
            _Fuel.Set(fuel);
            _Material.Set(material);
            Watch();
        }

        public void Increase(ReadonlyGameResources amount)
        {
            Material.Increase(amount.Material.Value);
            Energy.Increase(amount.Energy.Value);
            Fuel.Increase(amount.Fuel.Value);
        }

        public void Decrease(ReadonlyGameResources amount)
        {
            Material.Decrease(amount.Material.Value);
            Energy.Decrease(amount.Energy.Value);
            Fuel.Decrease(amount.Fuel.Value);
        }

        public bool IsLessThan(ReadonlyGameResources amount)
        {
            return 
                Material.Value <= amount.Material.Value &&
                Energy.Value <= amount.Energy.Value &&
                Fuel.Value <= amount.Fuel.Value;
        }

        public bool IsGreaterThan(ReadonlyGameResources amount)
        {
            return
                Material.Value >= amount.Material.Value &&
                Energy.Value >= amount.Energy.Value &&
                Fuel.Value >= amount.Fuel.Value;
        }

        public GameResource this[GameResourceType resourceType]
        {
            get
            {
                switch(resourceType)
                {
                case GameResourceType.Energy:
                    return _Energy;
                case GameResourceType.Fuel:
                    return _Fuel;
                case GameResourceType.Material:
                    return _Material;
                }
                
                return null;
            }
        }
        
        public ReadonlyGameResources GetReadOnly()
        {
            return new ReadonlyGameResources(this);
        }
        
        public GameResource Energy
        {
            get { return _Energy; }
        }
        
        public GameResource Fuel
        {
            get { return _Fuel; }
        }
        
        public GameResource Material
        {
            get { return _Material; }
        }

        void Watch()
        {
            _Energy.Changed += (source, args) => FireChanged();
            _Fuel.Changed += (source, args) => FireChanged();
            _Material.Changed += (source, args) => FireChanged();
        }

        void FireChanged()
        {
            if (Changed != null)
            {
                Changed(this, new EventArgs());
            }
        }

        public override string ToString()
        {
            return 
                "(Energy:" + _Energy.Value + 
                " Material:" + _Material.Value + 
                " Fuel:" + _Fuel.Value + ")";
        }
    }
}
